perm filename UDPSER.MAC[IP,SYS]1 blob
sn#739675 filedate 1984-02-04 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00011 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00003 00002 title UDPSer
C00004 00003 \
C00005 00004 subttl defintions describing a UDP leader UDPLen UDPIBH UDPIBf UDPObf UDPPnt
C00007 00005 subttl definitions
C00008 00006 subttl process incoming UDP message UDPIn UDPNCk NewLst
C00015 00007 subttl process a connection which has no DDB NewCon NewCo1 NowCon PLsSn NotExc
C00021 00008 subttl returns NoLead NoMess BadChk NoPort NoDDB BadCon NoIPCF NoITY BufFls
C00022 00009 subttl UDPMak UDPMak
C00026 00010 subttl UDPChk UDPChk
C00028 00011
C00029 ENDMK
C⊗;
title UDPSer
subttl provan
search f,s
NOWAITS<
search NetDef ; network definitions
>;NOWAITS
IFWAITS<SEARCH NETMAC>
search MacTen ; search only if symbol not found in NetDef
sall
$reloc
$high
XP VUDPSr,1 ; UDP version
comment \
this module contains the support routines for the User Datagram
protocol as defined in RFC-768.
\
subttl defintions describing a UDP leader ;⊗ UDPLen UDPIBH UDPIBf UDPObf UDPPnt
; see RFC-768 for details of this header.
UDPLen==:2 ; number of words in an UDP leader.
NOWAITS< ;Data is in CACDAT
$low ; define the storage needed
UDPIBH: block NBHLen ; buffer header.
UDPIBf: block UDPLen ; words needed for header
; the following block is used to create a UDP leader for output.
; it is filled and then converted to 36 bit buffers all under ScnOff.
UDPObf: block NBHLen+UDPLen ; output buffer for forming leader
>;NOWAITS
IFWAITS<
EXTERN UDPIBH,UDPIBF,UDPOBF
>;IFWAITS
$high ; back to protected code
UDPPnt: point 8,UDPIBf ; pointer to start loading the
; header block from the stream.
; define the actual header fields. position is the bit position of the
; left most bit.
;
; name word position width
; UDP uses the standard ports, StdSP and StdDP.
;DefFd. UDPSP, 0, 0, 16 ; source port of message
;DefFd. UDPDP, 0, 16, 16 ; destination port
DefFd. UDPSiz, 1, 0, 16 ; length of packet
DefFd. UDPChk, 1, 16, 16 ; UDP checksum
subttl definitions
IFWAITS<
;State codes for UDP, stored in STATE(F):
UD%CLS==0 ;Closed
UD%OPN==1 ;Open: waiting for input packet on local port
>;IFWAITS
subttl process incoming UDP message ;⊗ UDPIn UDPNCk NewLst
entry UDPIn ; only load this module if IP calls this routine
UDPIn::
move p2,MsgLen(f) ; get length of message through IP
ifn FtChck,< ; doing checksum
setz p3, ; clear checksum
move t1,p2 ; make sure to checksum length
; of UDP message before we
; convert it to length of segment.
pushj p,CSmHWd## ; checksum the length.
>
caige p2,UDPLen*4 ; cut length by that amount
jrst NoLead ; not enough message to read in leader
movei t1,UDPIBH ; get pointer to input leader
move t2,ABfLst(f) ; get last buffer so far
stor. t1,NBHNxt,(t2) ; make us their next
movem t1,ABfLst(f) ; and make us last (for grins)
move t1,UDPPnt ; point at the storage block
movei t2,UDPLen*4 ; length of leader in bytes
stor. t2,NBHCnt,UDPIBH ; store in buffer header
pushj p,GetLed## ; get the leader and checksum
jrst NoLead ; not enough bytes for leader.
load. t1,UDPSiz,UDPIBf ; get length from our packet
camle t1,p2 ; IP at least as big as we need?
jrst NoMess ; nope. forget it.
subi t1,UDPLen*4 ; cut length by amount of leader
movem t1,MsgLen(f) ; save length of UDP message
pushj p,GetMes## ; copy T1 bytes in.
jrst NoMess ; problem reading message
move p1,t1 ; save new stream pointer for later.
ifn FtChck,< ; doing checksumming
load. t1,UDPChk,UDPIBf ; get the checksum from the leader
jumpe t1,UDPNCk ; this guy doesn't do checksums
move t1,RmtAdr(f) ; get their address.
pushj p,CSmWrd## ; add in that checksum.
move t1,LclAdr(f) ; our address
pushj p,CSmWrd## ; checksum it.
move t1,Protcl(f) ; get the protocol
pushj p,CSmHWd## ; checksum that half a word
; bear in mind that the checksum we now have in P3 has, along with
; all the right stuff, its own one's complement. therefore, what
; we really have is <checksum> + -<checksum>, which is 0.
; further, since <checksum> has some bit on (otherwise the
; sender isn't checksuming and we wouldn't be here), it can be
; shown that the brand of one's complement 0 we must have is
; the version with all 1's. if that's what we have, we're ok.
; if not, the checksum failed.
hrrzs p3 ; get just the checksum
caie p3,<1←↑d16>-1 ; magic explained above
jrst BadChk ; checksum is bad.
UDPNCk: ; here to skip over the checksum checks because sender is not
; checksumming the messages.
>
aos UDPMsg## ; count another UDP message seen
move t1,RmtAdr(f) ; source (foreign host address)
load. t2,StdSP,UDPIBf ; get his port
movem t2,RmtPrt(f) ; and keep pseudo DDB up-to-date
load. t3,StdDP,UDPIBf ; get my port
movem t3,LclPrt(f) ; still keep pseudo DDB up-to-date
move t4,Protcl(f) ; get protocol
move p3,MsgLen(f) ; put length of this message
; somewhere where we can get
; it for the new DDB.
push p,f ; save current DDB, in case we fail
pushj p,FndDDB## ; scan network DDBs for the one
; that matches.
jrst NewCon ; this is one we haven't heard of
IFE FTAIP&FTEIP,<
pop p,(p) ; don't want that F any more.
>;IFE FTAIP&FTEIP
IFN FTAIP&FTEIP,<
;LCLADR(F) might be wrong if we did a listen and the incoming
;message wasn't from the ARPAnet. Here we fix it up.
POP P,T1 ;Get back pseudo-DDB
MOVE T1,LCLADR(T1)
MOVEM T1,LCLADR(F)
>;IFN FTAIP&FTEIP
NewLst: ; return here if we are now listening
; for an unknown port (exec port).
movem p3,MsgLen(f) ; remember the message length
; in the new DDB.
NOWAITS<
pass packet to owner
>;NOWAITS
IFWAITS<
SKIPE STATE(F) ;Is he ready for it?
SKIPE IBFTHS(F) ;Has he read the previous message?
JRST BUFFLS ;No, flush it
HLRM P1,IBFTHS(F) ;Store buffer ptr in convenient place in DDB
PUSHJ P,IMPNEW## ;Tell job about new data
POPJ P, ;That's all I can think of
>;IFWAITS
subttl process a connection which has no DDB ;⊗ NewCon NewCo1 NowCon PLsSn NotExc
NOWAITS<
; handle a connection to a port which is not listening.
; port number is in T3. old DDB (at this writing, always the pseudo
; DDB) is on the stack. it STAYS on the stack through most of
; this routine, so watch your ass or you'll try to popj p, to it.
NewCon:
; remember that we STILL have the old DDB on the stack.
; first check for a perpetual listen on that socket
movei t4,PlsLen-1 ; point at last entry
NewCo1: camn t3,PlsPrt(t4) ; is this it?
jrst PLsSn ; yes. a perptual listen seen.
sojge t4,NewCo1 ; count down
caxl t3,FrePrt ; is it below freely assigned ports?
jrst NotExc ; yes. not an exec port.
; now check for pemanent port services, handled through Telnet
skipe t1,t3 ; position our port number better
; (zero isn't legal)
PUSHJ P,WKPFND ;IS THIS SOCKET'S SERVICE IMPLEMENTED?
jrst NoPort ; remember this "error"
move t4,t1 ; save service offset
MOVEI J,0 ;NO JOB NUMBER YET
PUSHJ P,DDBGET## ;TRY FOR FREE DDB
jrst NoDDB ; can't get one
PUSHJ P,ITYGET## ;GET A PORT
jrst NoITY ; can't get one
MOVSI u,TTYKBD!TTYPTR
IORb u,TTYLIN(F) ; SET TTY BITS, get ITY's LDB into U
PUSHJ P,TSETBI## ;CLEAR INPUT BUFFER
PUSHJ P,TSETBO## ;CLEAR OUTPUT BUFFER
move t1,t4 ; position pointer to service.
HRRO T2,WKPSRV(T1) ;FETCH POINTER TO LOGICAL NAME
POP T2,DEVLOG(F) ;SET LOGICAL NAME INTO DDB
LDB T1,WKPTFC ;FETCH TTY FORCED COMMAND INDEX
pushj p,TTFORC## ;FORCE THE APPROPRIATE COMMAND
; here from perpetual listen setup
NowCon: pushj p,PrpDDB ; set essential DDB words
pop p,t2 ; get back the DDB which was used
; while the message was arriving.
;now fill in the information we know
move t1,RmtAdr(t2) ; get the foreign host address.
movem t1,RmtAdr(f) ; and save it the real DDB
move t1,NetAdr(t2) ; get ARPA address
movem t1,NetAdr(f) ; save in the DDB
move t1,RmtPrt(t2) ; get the source port (his port)
movem t1,RmtPrt(f) ; save in DDB
move t1,LclPrt(t2) ; get the destination port (my port)
movem t1,LclPrt(f) ; save in DDB
movei t1,S%List ; get state code "listen"
movem t1,State(f) ; make it this DDB's state
pushj p,NewLst ; go back a process this message
; as if nothing has happened.
move t2,State(f) ; now get the state
caie t2,S%List ; still listening?
popj p, ; no. just return.
pushj p,DDBFls## ; clear out DDB
pjrst DDBRel## ; and return it to free pool
; here to deal with a perpetual listen found
PLsSn: move j,PlsJob(t4) ; get job number listening
pushj p,DDBGet## ; get a DDB and assign it to this job.
jrst NoDDB ; can't. count and deny access
movei t1,PlsPID(t4) ; point at the PID to notify
hrrzi t2,DevNam(f) ; point at the device name in the
; DDB as the data to send.
hrli t2,1 ; just that one word, please.
setz j, ; mark as being sent from interupt
; level.
pushj p,SendSI## ; send the IPCF packet to the user
jrst NoIPCF ; oops. flush DDB and deny connection
jrst NowCon ; now process this packet
NotExc: pop p,f ; restore fake DDB.
movei u,TCPIBf ; point at TCP leader
move p3,TCPFlg(u) ; get the flags from leader.
jumpe p2,TryRst ; just reset if no options
hlrz t1,p2 ; get the first buffer of options
pushj p,RelBuf## ; free the options.
jrst TryRst ; try to send a reset and
; return the buffers and return.
>;NOWAITS
IFWAITS< ;For now, just discard these
NEWCON: AOS UDEPRT##
JRST BUFFLS
>;IFWAITS
subttl returns ;⊗ NoLead NoMess BadChk NoPort NoDDB BadCon NoIPCF NoITY BufFls
; message ended before leader was read in
NoLead: aos UDELed## ; error with leader
popj p, ; return
; bytes ended before message or ran out of buffers while reading it
NoMess: aos UDEMes## ; count error reading message in
popj p,
BadChk: aos UDEChk## ; checksum wrong. count it
pjrst BufFls ; flush out buffers and return
; subroutine to release all the buffers in our message.
BufFls: hlrz t1,p1 ; get first buffer of chain.
pjrst RelBuf## ; release the entire chain.
subttl UDPMak ;⊗ UDPMak
;++
; Functional description:
;
; put UDP leader (in 32 bit format) into fixed UDP output leader
; buffer. then link the buffer to the beginning of the
; current output stream. then send the message down to the
; next level of protocol for further processing.
;
;
; Calling sequence:
;
; move f,DDB
; pushj p,UDPMak
; <always returns here>
;
; Input parameters:
;
; f - DDB for connection
;
; Output parameters:
;
; none.
;
; Implicit inputs:
;
; data in DDB
;
; Implicit outputs:
;
; data in DDB
;
; Routine value:
;
; returns non-skip if can't get a buffer
;
; Side effects:
;
; adds a buffer to the beginning of the current output stream.
;--
UDPMak::
movei t1,UDPOBf ; point at the output leader space
exch t1,OBfFst(f) ; make us first, get old first
stor. t1,NBHNxt,UDPOBf ; link old first to us.
move t1,RmtPrt(f) ; get his port
stor. t1,StdDP,NBHLen+UDPOBf ; that's the destination port
move t1,LclPrt(f) ; get my port
stor. t1,StdSP,NBHLen+UDPOBf ; that's the source port
movei t1,UDPLen*4 ; get length in bytes
stor. t1,NBHCnt,UDPOBf ; save byte count for this buffer
addb t1,OBfByt(f) ; get a grand total in bytes.
stor. t1,UDPSiz,NBHLen+UDPOBf ; save in length word.
; one would add OPTIONS around here somewhere.
ifn FtChck,< ; doing checksums?
move t1,[point 16,NBHLen+UDPOBf]; starting pointer
movei t2,UDPLen*4 ; get length in bytes of leader
pushj p,CSmWds## ; and checksum it.
move t1,RmtAdr(f) ; get remote address
pushj p,CSmWrd## ; add it to checksum
move t1,LclAdr(f) ; local address, too
pushj p,CSmWrd## ; add it in.
move t1,Protcl(f) ; and get protocol
pushj p,CSmHWd## ; and add it in as well
move t1,OBfByt(f) ; get byte count of message
; plus leader
pushj p,CSmHWd## ; add that to checksum, too.
txc p3,msk.hw ; send one's complement of the sum
txnn p3,msk.hw ; if zero, make it...
movei p3,msk.hw ; ...the zero with all bits on
stor. p3,UDPChk,NBHLen+UDPOBf ; save the checksum in the leader.
>
ife FtChck,< ; not doing checksums
zero. t1,UDPChk,NBHLen+UDPOBf ; flag that we aren't checksumming
>
pjrst IpMake## ; call next level of protocol
subttl UDPChk ;⊗ UDPChk
;++
; Functional description:
;
; subroutine to do various once a second checks to an IMP DDB.
;
;
; Calling sequence:
;
; move f,DDB
; pushj p,UDPChk##
; <always returns here>
;
; Input parameters:
;
; f - DDB of an IMP device.
;
; Output parameters:
;
; none.
;
; Implicit inputs:
;
; DDB and queues
;
; Implicit outputs:
;
; DDB and queues
;
; Routine value:
;
; none.
;
; Side effects:
;
; may didle with output queues if it finds it needs to retransmit.
; may delete DDB altogether, although DevSer will still have the
; link to the next DDB. (HINT: call this after doing everything else.)
;--
NOWAITS<
UDPChk::
should need this
>;NOWAITS
$high
$LIT
END